liwe.lightbox = {};

// {{{ base docs
/**
Lightbox
========

Lightbox is a class aimed to display temporary modal forms to the user.

Lightbox is a *static* class, you don't have to instantiate it by yourself in your code.
You can access it with ``liwe.lightbox`` static class.

Lightbox requesters are stacked like a pile one over the other. You can programmatically create any number of lightboxes and the most recent one will always be visible over
all the previous lightboxes created.

You can only remove the top lightbox on the stack, using the ``liwe.lightbox.close()`` method.

.. warning:: 
	``lightbox.events`` not documented yet

**/
// }}}


liwe.lightbox.opacity = 70;
liwe.lightbox.fade = false;
liwe.lightbox._is_show = false;

liwe.lightbox._back_div  = null;
liwe.lightbox._front_div = [];

liwe.lightbox._max_zindex  = null;
liwe.lightbox._max_zindex_el  = 'div';
liwe.lightbox._zindexes = {};

liwe.lightbox.events = {
	"click" : null,
	"close" : null
};

liwe.lightbox.set_zindex = function ( id, zindex, is_easy )
{
	liwe.lightbox._zindexes [ id + ( is_easy ? '_win' : '' ) ] = zindex;
};

// {{{ liwe.lightbox.create ( id, w, h, x, y )
/**
.. function:: liwe.lightbox.create ( id, w, h, [ x, [ y ] ] )

	Creates a new lightbox area.

	:param id: the new lightbox id. This id can then be used to modify lightbox content. This field is mandatory.
	:param w:  lightbox width (in pixels). This field is mandatory.
	:param h:  lightbox height (in pixels). This field is mandatory.
	:param x:  lightbox x position (in pixels) This field is optional. If not passed the lightbox x position
		   will be computed to put the lightbox in the middle of the screen.

	:param y:  lightbox y position (in pixels). This field is optional. If not passed the lightbox y position
		   will be computed to put the lightbox in the middle of the screen.

	:rtype: this function returns nothing.
**/
liwe.lightbox.create = function ( id, w, h, x, y )
{
	var back = liwe.lightbox._add_back_div ( id );
	var div  = liwe.lightbox._add_front_div ( id, w, h, x, y );

	return div;
};
// }}}
// {{{ liwe.lightbox.created ()
/**
.. function:: liwe.lightbox.created ()

	This function simply checks if at least one lightbox is currently shown on the screen.
	This function returns ``true`` if there is at least one lightbox currently shows, ``false`` otherwise.

	:rtype: returns ``true`` if there is at least one lightbox currently shows, ``false`` otherwise.
**/
liwe.lightbox.created = function ()
{
	return liwe.lightbox._back_div != null;
};
// }}}
// {{{ liwe.lightbox.close ()
/**
.. function:: liwe.lightbox.close ()

	This function closes the topmost lightbox currenlty shown on the browser window.
**/
liwe.lightbox.close = function ()
{
	var d;

	d = liwe.lightbox._front_div.pop ();
	if ( ! d ) return;
	liwe.dom.remove_element ( d );

	if ( liwe.lightbox.events [ 'close' ] ) liwe.lightbox.events [ 'close' ] ();

	liwe.dom.remove_element ( liwe.lightbox._back_div );
	liwe.lightbox._back_div = null;
};
// }}}
// {{{ liwe.lightbox.show ()
/**
.. function:: liwe.lightnox.show ()

	This function shows on browser window the last created lightbox.
**/
liwe.lightbox.show = function ()
{
	var div = liwe.lightbox._front_div [ liwe.lightbox._front_div.length -1 ];

	liwe.fx.set_opacity ( liwe.lightbox._back_div, liwe.lightbox.opacity );
	liwe.lightbox._back_div.style.display = "block";

	if ( liwe.lightbox.fade )
	{
		div.style.display = "block";

		liwe.fx.fade_in ( div );
	} else 
		liwe.fx.set_opacity ( div, 100 );
};
// }}}
// {{{ liwe.lightbox.easy ( id, title, w, h, x, y )
/**
.. function:: liwe.lightnox.easy ( id, title, w, h, x, y )

	This is a commodity function that will call the ``liwe.lightbox.create()`` method to build a new lightbox,
	sets a custom layout (with a close button on the upper right corner of the lightbox screen) and then calls
	the ``liwe.lightbox.show()`` to show it to the user.

	:param id: the new lightbox id. This id can then be used to modify lightbox content. This field is mandatory.
	:param title: the lightbox title that will be shown on the window bar.
	:param w:  lightbox width (in pixels). This field is mandatory.
	:param h:  lightbox height (in pixels). This field is mandatory.
	:param x:  lightbox x position (in pixels) This field is optional. If not passed the lightbox x position
		   will be computed to put the lightbox in the middle of the screen.

	:param y:  lightbox y position (in pixels). This field is optional. If not passed the lightbox y position
		   will be computed to put the lightbox in the middle of the screen.

	:rtype: this function returns nothing.
**/
liwe.lightbox.easy = function ( id, title, w, h, x, y )
{
	var div = liwe.lightbox.create ( id + "_win", w, h, x, y );
	var s;

	div.className = "lightbox_easy";
	if ( liwe.lightbox.fade ) liwe.fx.set_opacity ( div, 0 );

	s  = '<div class="title">' + title;
	s += '<div class="close" onclick="liwe.lightbox.close()"></div></div><div id="' + id + '"></div>';

	div.innerHTML = s;

	// TODO: fare il "pallino"

	liwe.lightbox.show ();
};
// }}}

// PRIVATE METHODS

// {{{ liwe.lightbox._add_back_div ()
liwe.lightbox._add_back_div = function ( id )
{
	var d = liwe.lightbox._back_div;
	var max_zindex = liwe.lightbox._zindexes.get ( id, liwe.lightbox._max_zindex );
	if ( max_zindex == null ) max_zindex = liwe.dom.get_highest_zindex ();
	//var max_zindex = ( ! liwe.lightbox._max_zindex ) ? liwe.lightbox._get_highest_zindex () : liwe.lightbox._max_zindex;
	
	if ( ! d ) 
	{
		d = liwe.dom.create_element ( "div", "liwe_lightbox" );

		d.style.display = 'none';
		d.style.backgroundColor = "black";

		liwe.lightbox._back_div = d;
	}

	d.style.zIndex = max_zindex + 5;
	d.style.top = 0;
	d.style.left = 0;
	if ( liwe.utils.supports ( 'transition' ) )
	{
		d.style.bottom = 0;
		d.style.right = 0;
	} else {
		var size = liwe.lightbox._get_size ();
		d.style.width  = size.bw + "px"; // "100%";
		d.style.height = size.bh + "px";
	}
	d.style.position = "fixed"; // "absolute";

	liwe.events.add ( d, "click", liwe.lightbox._back_click );

	return d;
};
// }}}
// {{{ liwe.lightbox._back_click ()
liwe.lightbox._back_click = function ()
{
	if ( liwe.lightbox.events [ 'click' ] ) liwe.lightbox.events [ 'click' ] ();
};
// }}}
// {{{ liwe.lightbox._add_front_div ( idm wm h, x, y )
liwe.lightbox._add_front_div = function ( id, w, h, x, y )
{
	var d = liwe.lightbox._back_div;
	var div = liwe.dom.create_element ( "div", id );
	var max_zindex = liwe.lightbox._zindexes.get ( id, liwe.lightbox._max_zindex );
	if ( max_zindex == null ) max_zindex = liwe.dom.get_highest_zindex ();
	//var max_zindex = ( ! liwe.lightbox._max_zindex ) ? liwe.lightbox._get_highest_zindex () + 1 : liwe.lightbox._max_zindex;
	var res, r, b;

	y = ( ! y ) ? 10 : y;

	if ( w == 'auto' )
	{
		x = 10;
		r = 10;
	}

	if ( h == 'auto' )
	{
		b = 10;
	}

	if ( !b && !r )
	{
		w += 80;
		h += 80;

		res = this._calc_size ( w, h, x, y );

		w = res [ 0 ];
		h = res [ 1 ];
		x = res [ 2 ];
		y = res [ 3 ];
	}

	div.style.zIndex = max_zindex + 10;
	div.style.width  = w + "px";
	div.style.height = h + "px";
	div.style.left = x + "px";
	if ( r ) div.style.right = r + "px";
	if ( b ) div.style.bottom = b + "px";
	//div.style.top  = y + "px";
	div.style.top  = y + "px";
	div.style.position = "absolute"; //"fixed";

	liwe.lightbox._front_div.push ( div ); // = div;
	liwe.lightbox._front_div_id = id; 

	return div;
};
// }}}
// {{{ liwe.lightbox.set_content ( idi, content )
/*
	params:
		- lb_id			lightbox name
		- content		content to show in lightbox
		- overflow		true: css overflow set to 'auto' otherwise 'visible'
		- cback			callback: it will be called as soon as lightbox have been resized
**/
liwe.lightbox.set_content = function ( lb_id, content, overflow, cback )
{

	try {
		var front_div = liwe.lightbox._front_div.slice ( -1 ) [ 0 ];
	} catch ( err ) {
		console.debug ( " no front_div " );
		return;
	}
	//init vars
	var els, foot, cnt, imgs, i, timer = {};
	var extra = 0, l = 0, loaded = 0;
	var tags = { 'img' : [], 'iframe' : [] };
	var id = $el( lb_id );
	if ( ! id ) return;
	//find extra divs height
	function _extra_height ()
	{
		var tmp = front_div.getElementsByTagName ( 'div' );
		for ( i = 0; i < tmp.length; i ++ )
		{
			extra += liwe.dom.get_size ( tmp [ i ] ) [ 1 ];
		}	
	};
	//call set size when all images/iframes have been loaded
	function _onload ( e )
	{
		loaded += 1;
		if ( loaded == l ) _set_size ();
	}
	//set lightbox size based on content size
	function _set_size ()
	{
		//set content div outside viewport
		cnt.style.position = 'absolute';
		//get content div size and resize lightbox
		var s = liwe.dom.get_size ( cnt );
		var w = s [ 0 ], h = s [ 1 ] + extra;
		liwe.lightbox.set_size ( w, h, null, null, function () 
			{ 
				id.style.visibility = 'visible'; 
				front_div.style.width = w;
				front_div.style.height = h;	
			} );
		//set back content div in position
		cnt.style.position = 'relative';
		cnt.style.left = '0';
		if ( cback ) cback ();
		front_div.style.visibility = 'visible';
		//id.style.visibility = 'visible';
	}	
	//hide lightbox before resize
	front_div.style.visibility = 'hidden';
	front_div.style.width = 'auto';	
	front_div.style.height = 'auto';	
	front_div.style.overflow = ( overflow ) ? 'auto' : 'visible';

	id.style.visibility = 'hidden';
	id.style.width = 'auto';	
	id.style.height = 'auto';	
	id.innerHTML = '';

	_extra_height ();
	//create content div
	cnt = document.createElement ( 'div' );
	cnt.innerHTML = content;
	//add a div to clear any float 
	foot = document.createElement ( 'div' );
	foot.style.clear = 'both';
	cnt.appendChild ( foot );
	//append created content div to actual lightbox content div
	id.appendChild ( cnt );
	//check if content has any external media
	tags.iterate ( function ( v, k )
		{
			tags [ k ] = id.getElementsByTagName ( k );
			var tl = tags [ k ].length;
			l += tl;
			for ( i = 0; i < tl; i ++ )
			{
				//tags [ k ][ i ][ 'time' ] = setTimeOut ( _onload, 500 );
				//set onload function to images
				tags [ k ][ i ].onload = function () { _onload (); };  
			};
		} );
	//if no images, then call _set_size right away
	l = 0;
	if ( l < 1 ) _set_size ();
};
// }}}
// {{{ liwe.lightbox.set_size ( w, h, x, y )
liwe.lightbox.set_size = function ( w, h, x, y, cback )
{
	var res;
	var div = document.getElementById ( liwe.lightbox._front_div_id );

	if ( ! div ) 
	{
		console.warning ( "Could not find DIV: %s", liwe.lightbox._front_div_id );
		return;
	}

	res = this._calc_size ( w, h, x, y );

	w = res [ 0 ];
	h = res [ 1 ];
	x = res [ 2 ];
	y = res [ 3 ];

	div.style.left = x + "px";
	div.style.top  = y + "px";
	if ( liwe.utils._dom_supports ( 'transform' ) )
	{
		liwe.fx.resize ( div, w + "px", h + "px", cback );
		return;
	}
	div.style.width  = w + "px";
	div.style.height = h + "px";
	if ( cback ) cback ();
};
// }}}
// {{{ liwe.lightbox._get_size ()
liwe.lightbox._get_size = function ()
{

	var bw, bh, sh, sw, ih, iw;
	var D = document;

	bh = Math.max (
		Math.max ( D.body.offsetHeight, D.documentElement.offsetHeight ),
		Math.max ( D.body.clientHeight, D.documentElement.clientHeight )
		//,window.innerHeight
	);

	bw = Math.max (
		Math.max ( D.body.offsetWidth, D.documentElement.offsetWidth ),
		Math.max ( D.body.clientWidth, D.documentElement.clientWidth )
		//, window.innerWidth
	);

	/*
	sh = Math.max ( Math.max ( D.body.scrollHeight, D.documentElement.scrollHeight ), bh );
	sw = Math.max ( Math.max ( D.body.scrollWidth, D.documentElement.scrollWidth ), bw );
	*/
	ih = ( window.innerHeight ) ? window.innerHeight : D.documentElement.clientHeight;
	iw = ( window.innerHeight ) ? window.innerWidth : D.documentElement.clientWidth;

	sh = Math.max ( D.body.scrollTop, D.documentElement.scrollTop );

	//console.debug ( "Get Size: bw: " + bw + " - " + bh + " - iw: " + iw + " - " + ih );

	return { 'bh' : bh, 'bw' : bw, 'sh' : sh, 'iw' : iw, 'ih' : ih };
};
// }}}
// {{{ liwe.lightbox._calc_size = function ( w, h, x, y )
liwe.lightbox._calc_size = function ( w, h, x, y )
{
	var size = liwe.lightbox._get_size () ;

	if ( ! w ) w = 0;
	if ( ! h ) h = 0;
	if ( ! x ) x = 0;
	if ( ! y ) y = 0;

	//y = size.sh + 5;
	x = Math.abs ( size.bw - w ) / 2;
	y = size.sh + 10;

	var margin_h = size.ih; // size.bh;
	if ( margin_h > h )
 		y = Math.abs ( ( ( margin_h - h ) / 2 ) + size.sh );
	//FIXME: y fissa per testing
	//y = 10;
	return [ w, h, x, y ];
};
// }}}
// {{{ liwe.lightbox._get_highest_zindex = function ()
liwe.lightbox._get_highest_zindex = function ()
{
	console.warn ( 'DEPRECATED! use liwe.dom.get_highest_zindex()' );
	var el = liwe.lightbox._max_zindex_el;
	var z = 0, tmp, val;
	var elems = document.getElementsByTagName ( el );
	for ( var c = 0; c < elems.length; c++ )
			{
				//if ( document.defaultView ) val = document.defaultView.getComputedStyle ( elems[c], null ).getPropertyValue ( 'z-index' );
				if ( elems [ c ].currentStyle ) val = elems [ c ].currentStyle [ 'zIndex' ];
				if ( window.getComputedStyle ) val = window.getComputedStyle ( elems[c], null ).getPropertyValue ( 'z-index' );

				tmp = parseInt ( val, 10 );
			
				if ( ( ! isNaN ( tmp ) ) && ( tmp  > z ) ) z = tmp;
			} 
	return z;
};
// }}}
